home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / SKY.ZIP / TESTSKY.ASM < prev    next >
Assembly Source File  |  1996-02-14  |  7KB  |  228 lines

  1. ;----------------------------------------------------------------------
  2. ; ProjectSky - Project a 256x256 map to the sky
  3. ;
  4. ; Turbo Pascal near-callable as
  5. ; ProjectSky(Map:Pointer;Buffer:Pointer;X,Y,Height:longint);
  6. ;
  7. ; X,Y are the coords of the viewpoint (16.16 fixed point)
  8. ; Height is the distance from the sky to the viewpoint (16.16)
  9. ;
  10. ; This routine has been timed at ~4.8 cycles/pixel for the inner loop
  11. ; rendering to an offscreen buffer on a 486 with 256K cache.
  12. ;
  13. ; WARNING: this code is somewhat kludgy.
  14. ;
  15. ; In particular, I have done some nasty things to gain an extra
  16. ; register (sp) for the main unrolled loop, and at the same time
  17. ; modified the stack segment register as a general segment register.
  18. ; This is VERY NAUGHTY and I don't recommend doing it :). The instruction
  19. ; ordering is also a bit counter-intuitive in the inner loop to avoid
  20. ; register contentions and AGIs on both the Pentium and the 486.
  21. ;
  22. ; The code is also somewhat more spaghetti-ish than it need be, since
  23. ; this is cut down from a more general routine that allows pitching of
  24. ; the viewpoint as well as other things.
  25. ;
  26. ; One obvious improvement is to have two inner loops: one for close bits
  27. ; which dithers the sky map, the other for distant bits which interpolates
  28. ; between values, thus avoiding some of the aliasing you get close to the
  29. ; horizon. If anyone does this and wants to send me a copy, I'd be
  30. ; grateful :)
  31. ;
  32. ;                Mark Mackey (mdm1004@cus.cam.ac.uk)
  33. ;
  34. ; This code is Copyright (C) 1996 Mark Mackey. Use, modification,
  35. ; and redistribution of this code is freely permitted, provided that
  36. ; the original author is acknowledged.
  37. ;----------------------------------------------------------------------
  38.  
  39. .model small,pascal
  40. .386
  41.  
  42. BORDER        equ    0    ; Size of screen border
  43. BUFFERWIDTH    equ    256    ; Width of screen buffer
  44.  
  45. ; General view parameters
  46. d        equ      1    ; 2^d is the focal length
  47. StartLine       equ     100    ; Starting line value
  48. EndLine        equ     4    ; End line value
  49.  
  50.                 ; Total number of lines drawn is
  51.                 ; StartLine-Endline. The horizon is
  52.                 ; at 0 but it's generally worth clipping
  53.                 ; the sky a few lines above the horizon
  54.                 ; since you get nasty aliasing in the
  55.                 ; last few lines. Change StartLine to
  56.                 ; 97 and Endline to 1 to see what I
  57.                 ; mean :).
  58.  
  59. ;Sky
  60. xscale        equ    6       ; scaling factors: change these to taste.
  61. zscale        equ    1       ; Note that these values are logarithmic,
  62.                 ; ie increasing them by 1 doubles the
  63.                 ; scale.
  64.  
  65. Mapz        equ    -4
  66. Mapx        equ     -8    ; local variables.
  67. STACK_FRAME_SIZE equ     8
  68.  
  69. .DATA
  70. Saved_ss    dw    (?)    ; Used to hold ss and sp during inner loop.
  71. Saved_sp    dw    (?)
  72.  
  73. .CODE
  74.  
  75. MyShl  MACRO  reg,int   ; General purpose shl by a constant. Handles negatives.
  76. IF (int) EQ 0
  77. ELSE                            ;ignore shifts by zero
  78.   IF (int) LT 0
  79.      MySar reg,-int
  80.   ELSE
  81.      IF (int) EQ 1
  82.            add   reg,reg        ; Faster than shl xx,1
  83.      ELSE
  84.            shl   reg,int
  85.      ENDIF
  86.   ENDIF
  87. ENDIF
  88. ENDM
  89.  
  90. MySar  MACRO  reg,int   ; General purpose sar by a constant. Handles negatives.
  91. IF (int) EQ 0
  92. ELSE                            ; Ignore shifts by zero
  93.   IF (int) LT 0
  94.      MyShl reg,-int
  95.   ELSE
  96.      sar   reg,int        ; Arithmetic shift.
  97.   ENDIF
  98. ENDIF
  99. ENDM
  100.  
  101.     PUBLIC ProjectSky
  102. ProjectSky proc near Pascal Map:FAR PTR,Buffer:FAR PTR,X:DWORD,Y:DWORD,Height:DWORD
  103. ; Kills all registers except ds,ss,sp,bp
  104.     sub   sp,STACK_FRAME_SIZE
  105.     push  ds
  106.     cld
  107.     mov   ax,_DATA
  108.     mov   gs,ax
  109.     les   di,[Buffer]
  110.     add   di,BORDER
  111.     xor   ecx,ecx
  112.     mov   cx,StartLine    ; Counter=value of first line
  113. align 16
  114. @@startloop:
  115.     mov   ebx,ecx
  116.     shl   ebx,8             ;ebx holds counter in 24.8
  117.     xor   edx,edx
  118.     mov   eax,[height]
  119.     shld  edx,eax,8+d
  120.     MyShl eax,8+d
  121.     div   ebx
  122.                 ;eax holds height*d/ebx 16.16
  123.                 ; save as Mapz
  124.  
  125.         mov   dword ptr [bp+Mapz],eax
  126.  
  127.         MyShl eax,7-xscale-d
  128.         neg   eax
  129.         add   eax,[x]
  130.     mov   [bp+Mapx],eax     ;mapx=(-128*mapz) shr xscale (scaling) div d + x in 16.16
  131.                 ; This is the starting x value for the map
  132.  
  133.         mov   eax,[bp+Mapz]
  134.     MyShl eax,zscale        ;mapz=mapz*2^zscale (scaling)
  135.     mov   ebx,[y]
  136.     add   eax,ebx           ;eax = mapz + y in 16.16
  137.  
  138.     shr   eax,8             ;ah holds map y value for this line.
  139.  
  140.         mov   ebx,[bp+Mapx]
  141.     sar   ebx,16        ; Whole value of mapx in bx
  142.     mov   al,bl             ; mapx mod 256 placed in al
  143.                 ; => ax holds map starting point (integer)
  144.     lds   si,[Map]
  145.     add   si,ax
  146.     mov   eax,[bp+mapx]     ; ax holds fractional part of mapx
  147.                 ; => si.ax holds complete map starting
  148.                 ; point in 16.16 fixed point
  149.  
  150.         mov   ebx,[bp+mapz]
  151.         shr   ebx,xscale+d      ;ebx = delta = mapz shr (xscale+d) (scaling)
  152.         mov   edx,ebx
  153.     shr   edx,16            ;delta in dx.bx in 16:16 fixed point
  154.  
  155.                 ; delta is the value we step across the
  156.                 ; sky map with.
  157.  
  158.     push  cx        ; save counter
  159.  
  160.     cli                     ;Prevent interrupts since stack is
  161.                 ;clobbered below
  162.     push  bp
  163.     mov   gs:[Saved_sp],sp    ;save stack pointer: can't use stack
  164.     mov   gs:[Saved_ss],ss  ;until restored!
  165.  
  166.     mov   sp,es
  167.     mov   ss,sp        ; ss points to buffer. We do this to
  168.                 ; avoid segment overrides in the inner
  169.                 ; loop, which really slow the Pentium
  170.                 ; down.
  171.  
  172.     mov   bp,di        ; ss:bp points to current location in buffer
  173.  
  174.         mov   di,si
  175.     mov   sp,ax             ; di.sp = si.ax = map starting point
  176.  
  177.     add   sp,bx             ;initialise odd start value: add delta
  178.     adc   di,dx
  179.  
  180.     and   cx,0001        ;Swap odd/even dither depending on
  181.                 ; lsb of cx
  182.     jnz   @odd
  183. @even:
  184.     add   ax,8000h        ; add 0.5 for dithering on even bytes
  185.     adc   si,0
  186.     jmp   @ditherOK
  187. @odd:
  188.     add   sp,8000h          ; add 0.5 for dithering on odd bytes
  189.     adc   di,0
  190.  
  191. @ditherOK:
  192.     add   bx,bx               ;double delta
  193.     adc   dx,dx
  194.  
  195.     add   ax,bx             ;setup due to rearranged instructions in
  196.     adc   si,dx             ; main loop
  197.     add   sp,bx             ;
  198.  
  199.         offs=0
  200. rept (BUFFERWIDTH-BORDER*2)/2     ; 2 pixels/loop. Pentium pipeline use below:
  201.     mov   cl,ds:[si]         ;V0
  202.     adc   di,dx              ;U1
  203.     add   ax,bx              ;V1
  204.     mov   ch,ds:[di]         ;U3 (AGI on di)
  205.     adc   si,dx              ;U4
  206.     add   sp,bx              ;V4
  207.     mov   ss:[bp+offs],cx    ;U5
  208.     offs=offs+2
  209. endm
  210.         mov   di,bp
  211.  
  212.     mov   ss,gs:[Saved_ss]        ; restore stack
  213.     mov   sp,gs:[Saved_sp]
  214.     pop   bp
  215.  
  216.         sti
  217.     add   di,BUFFERWIDTH        ; set up for next row
  218.     pop   cx
  219.     dec   cx
  220.     cmp   cx,EndLine        ; Have we finished?
  221.     jge   @@startloop
  222.  
  223. @End:
  224.         pop   ds
  225.     ret                ; Done!
  226. ProjectSky  endp
  227.  
  228. end